/*
 * @Author: Clark
 * @Email: haixuanwoTxh@gmail.com
 * @Date: 2023-01-13 16:18:49
 * @LastEditors: Clark
 * @LastEditTime: 2023-01-13 16:31:32
 * @Description: file content
 */

#include <sys/wait.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>

int system(const char *cmdstring)
{
    pid_t pid;
    int status;
    struct sigaction ignore, saveintr, savequit;
    sigset_t  chldmask, savemask;

    if (NULL == cmdstring)
    {
        return 1;
    }

    ignore.sa_handler = SIG_IGN;
    sigemptyset(&ignore.sa_mask);
    ignore.sa_flags = 0;

    if (sigaction(SIGINT, &ignore, &saveintr) < 0)
    {
        return -1;
    }

    if (sigaction(SIGQUIT, &ignore, &saveintr) < 0)
    {
        return -1;
    }

    sigemptyset(&chldmask);
    sigaddset(&chldmask, SIGCHLD);

    if (sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0)
    {
        return -1;
    }

    if ((pid = fork()) < 0)
    {
        status = -1;
    }
    else if (0 == pid)
    {
        sigaction(SIGINT, &saveintr, NULL);
        sigaction(SIGQUIT, &savequit, NULL);
        sigprocmask(SIG_SETMASK, &savemask, NULL);
        execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
        _exit(127);
    }
    else
    {
        while (waitpid(pid, &status, 0) < 0)
        {
            if (EINTR != errno)
            {
                status = -1;
                break;
            }
        }
    }

    if (sigaction(SIGINT, &saveintr, NULL) < 0)
    {
        return -1
    }

    if (sigaction(SIGQUIT, &savequit, NULL) < 0)
    {
        return -1
    }

    if (sigprocmask(SIG_SETMASK, &savemask, NULL) < 0)
    {
        return -1
    }

    return status;
}
